#include "widget.h"

/*timeOut() 函数处理了贪吃蛇每次移动时的逻辑。
 * 首先，它遍历了奖励节点列表 rewardNode，检查贪吃蛇头部是否与某个奖励节点重叠。
 * 如果重叠，则根据奖励节点的大小给贪吃蛇增加分数（flage 变量用于记录分数），然后移除该奖励节点。
 * 接着，根据贪吃蛇当前的移动方向 moveFlage，使用 addTopRectF()、addDownRectF()、addLeftRectF()、addRightRectF() 函数
 * 将新的贪吃蛇节点插入到贪吃蛇头部的相邻位置。最后，使用 deleteLastRectF() 函数删除贪吃蛇尾部的节点。*/

void Widget::timeOut()
{
    int flage = 1;
    for(int i=0; i<rewardNode.length(); i++){
        if(rewardNode.at(i).contains(snake.at(0).topLeft()+QPointF(snakeNodeWidth/2,snakeNodeHeight/2))){
            if(rewardNode.at(i).width()>snakeNodeWidth){
                flage += 2; // 大食物+2
            }
            flage++; // 小食物+1
            rewardNode.removeAt(i);
            break;
        }
    }
    while(flage--){
        switch (moveFlage) {
        case Up:
            addTopRectF();
            break;
        case Down:
            addDownRectF();
            break;
        case Right:
            addRightRectF();
            break;
        case Left:
            addLeftRectF();
            break;
        default:
            break;
        }
    }
    deleteLastRectF();

    update();
}

/*addTopRectF()、addDownRectF()、addLeftRectF()、addRightRectF() 函数分别用于处理贪吃蛇向上、向下、向左、向右移动时的逻辑。
 * 它们首先检查贪吃蛇是否会超出边界，然后根据移动方向在贪吃蛇头部的相邻位置插入一个新的贪吃蛇节点。*/

// 向上移动
void Widget::addTopRectF()
{
    if(snake.at(0).y()-snakeNodeHeight < 0){
        snake.insert(0,QRectF(QPointF(snake.at(0).x(),this->height()-snakeNodeHeight),
                               QPointF(snake.at(0).x()+snakeNodeWidth,this->height())));
    }else{
        snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(0,-snakeNodeHeight),snake.at(0).topRight()));
    }
}

// 向下移动
void Widget::addDownRectF()
{
    if(snake.at(0).y()+snakeNodeHeight*2 > this->height()){
        snake.insert(0,QRectF(QPointF(snake.at(0).x(),snakeNodeHeight),
                               QPointF(snake.at(0).x()+snakeNodeWidth,0)));
    }else{
        snake.insert(0,QRectF(snake.at(0).bottomLeft(),snake.at(0).bottomRight()+QPointF(0,snakeNodeHeight)));
    }
}

// 向左移动
void Widget::addLeftRectF()
{
    if(snake.at(0).x()-snakeNodeWidth < 0){
        snake.insert(0,QRectF(QPointF(this->width()-snakeNodeWidth,snake.at(0).y()),
                               QPointF(this->width(),snake.at(0).y()+snakeNodeHeight)));
    }else{
        snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(-snakeNodeWidth,0),snake.at(0).bottomLeft()));
    }
}

// 向右移动
void Widget::addRightRectF()
{
    if(snake.at(0).x()+snakeNodeWidth*2 > this->width()){
        snake.insert(0,QRectF(QPointF(0,snake.at(0).y()),
                               QPointF(snakeNodeWidth,snake.at(0).y()+snakeNodeHeight)));
    }else{
        snake.insert(0,QRectF(snake.at(0).topRight(),snake.at(0).bottomRight()+QPointF(snakeNodeWidth,0)));
    }
}

/*deleteLastRectF() 函数用于删除贪吃蛇尾部的节点，以实现贪吃蛇的移动效果。*/

void Widget::deleteLastRectF()
{
    snake.removeLast();
}


/*在 keyPressEvent 函数中，根据用户按下的按键来改变贪吃蛇的移动方向。
 *  如果游戏结束且用户按下了回车键，则重新初始化游戏。
 *  如果用户按下了空格键，则控制游戏的暂停和继续。*/

void Widget::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()){
    case Qt::Key_Up:
        if(moveFlage != Down){
            moveFlage = Up;
        }
        break;
    case Qt::Key_Down:
        if(moveFlage != Up){
            moveFlage = Down;
        }
        break;
    case Qt::Key_Right:
        if(moveFlage != Left){
            moveFlage = Right;
        }
        break;
    case Qt::Key_Left:
        if(moveFlage != Right){
            moveFlage = Left;
        }
        break;
    case Qt::Key_Enter:
    case Qt::Key_Return:
        if(gameOver){
            snake.clear();
            rewardNode.clear();
            moveFlage = Up;
            snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight));
            addTopRectF();
            addTopRectF();
            //首先生成一个奖励节点
            rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth));
            timer->start(time);
            rewardTimer->start(time*30);
            gameOver = false;
        }
        break;
    case Qt::Key_Space:
        if(gameStart && !gameOver){
            timer->start(time);
            rewardTimer->start(time*30);
            gameStart = false;
        }else if(!gameStart && !gameOver){
            timer->stop();
            rewardTimer->stop();
            gameStart = true;
        }
        break;
    default:
        break;
    }
}

/*snakeStrike 函数用于判断贪吃蛇是否发生碰撞。
 * 通过两重循环遍历贪吃蛇的所有节点，并检查是否有重叠的节点，
 * 若有则返回 true 表示发生了碰撞，否则返回 false 表示未发生碰撞。*/
bool Widget::snakeStrike()
{
    for(int i=0; i<snake.length(); i++){
        for(int j=i+1; j<snake.length(); j++){
            if(snake.at(i) == snake.at(j)){
                return true;
            }
        }
    }
    return false;
}
